import { debounce } from  "../utils/index"
import { wsUrl } from "./request"

class Scoket {
  wsbaseUrl = ""
  wsConnect = null
  connectLoading = false
  event = {}

  // 重连次数
  reconnectNumber = {
    max: 100,
    current: 0
  }
  // 心跳
  heartbeat = {
    setInterval: null,
    pingInterval: 20000,
  }
  // 重连
  reconnect = debounce(function() {
    if(this.reconnectNumber.current < this.reconnectNumber.max){
      this.reconnectNumber.current++
      this.init()
    }
  },3000,false)
  // 房间
  room = {id: "",fn (){}}
  // 列表
  listPage = {flag: false, fn(){}}
  // 标记
  badge = false

  constructor(){
    this.isConnect()
  }

  isConnect() {
    const token = wx.getStorageSync('token')
    this.loginType = wx.getStorageSync('loginType')

    if(!token || !this.loginType ||this.wsConnect) return

    this.wsbaseUrl = `${wsUrl}?type=${this.loginType}&token=${token}`

    this.init()
  }

  init() {
    if(this.connectLoading) return
    this.connectLoading = true
    this.wsConnect = wx.connectSocket({
      url: this.wsbaseUrl ,
      perMessageDeflate: true,
      timeout: 5000,
      success: (res) => {
        setTimeout(_=>{
          this.wsConnect.onOpen(this.onOpen.bind(this))
          this.wsConnect.onMessage(this.onMessage.bind(this))
          this.wsConnect.onError(this.onError.bind(this))
          this.wsConnect.onClose(this.onClose.bind(this))
        },10)
      },
      fail: (res) => {
        console.log("fail",res)
      },
      complete: (res) => {
        this.connectLoading = false
      },
    })

  }

  send(data,callBack,errBack) {
    this.wsConnect.send({
      data: JSON.stringify(data),
      success: () => {
        if(typeof callBack === 'function') callBack(data)
      },
      fail: () => {
        if(typeof errBack === 'function') errBack(data)
        this.reconnect()
      }
    })
  }

  onRoom(id,fn) {
    this.room = {id,fn}
  }
  
  removeRoom() {
    this.room = {}
  }

  onList(flag,fn){
    this.listPage = {flag,fn}
  }

  setBadge() {
    if(this.badge){
      wx.showTabBarRedDot({
        index: 1,
        success: () => {
          this.badge = false
        }
      })
    }
  }

  on(name,callBack) {
    if(typeof callBack !== 'function') throw new Error("必须绑定函数")
    this.event[name] = callBack
    return this
  }

  remove(name) {
    delete this.event[name]
  }
  
  emit(name,data) {
    if(name) {
      this.event[name] && this.event[name](data)
    }else {
      for (const key in this.event) {
        this.event[key](data)
      }
    }
  }

  onOpen(res) {
    console.log("onOpen", res)
    this.reconnectNumber.current = 0
    this.heartbeat.setInterval = setInterval(_=>{
      this.send({action: "ping"})
    },this.heartbeat.pingInterval) 
  }

  onMessage(res ) {
    try {
      const ops = JSON.parse(res.data)
      if(ops.type === 'onMessage'){
        const data = ops.data
        if(this?.room?.id == data.sender){
          this.room.fn(data)
        }else {
          if(this.listPage.flag){
            this.listPage.fn(data)
          }else {
            wx.showTabBarRedDot({
              index: 1,
              fail: (err) => {
                this.badge = true
              }
            })
          }
        }
      }else {

      }
    } catch (error) {
    }
  }

  onError(res) {
    console.log("onError", res)
    this.closeHeartbeat()  
    this.reconnect()
  }

  onClose(res) {
    console.log("onClose", res)
    if(res.code !== 1000){
      this.reconnect()
    }
    this.closeHeartbeat()  
  }

  closeHeartbeat(){
    this.heartbeat.setInterval && clearInterval(this.heartbeat.setInterval)
  }

  close() {
    if(this.wsConnect) {
      this.wsConnect.close()
      this.wsConnect = null
    }
    
  }
}


export default Scoket